// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html

import BezierCurve from "./BezierCurve";
const { ccclass, property, executeInEditMode } = cc._decorator;

@ccclass
@executeInEditMode
export default class BezierPath extends cc.Component {
    @property({
        editorOnly: true,
    })
    editing: boolean = false;

    @property
    close: boolean = false;

    @property(cc.Vec2)
    offset: cc.Vec2 = cc.Vec2.ZERO;

    @property(cc.Vec2)
    _points: cc.Vec2[] = [];

    @property({
        type: cc.Vec2
    })
    get points(): cc.Vec2[] {
        return this._points;
    }

    set points(value) {
        this._points = value;
    }

    @property(cc.Vec2)
    _c1: cc.Vec2[] = [];

    @property({
        type: cc.Vec2
    })
    get c1(): cc.Vec2[] {
        return this._c1;
    }

    set c1(value) {
        this._c1 = value;
    }

    @property(cc.Vec2)
    _c2: cc.Vec2[] = [];

    @property({
        type: cc.Vec2
    })
    get c2(): cc.Vec2[] {
        return this._c2;
    }

    set c2(value) {
        this._c2 = value;
    }

    private _beziers: Array<BezierCurve> = [];
    private _bezierLengths: Array<number> = [];
    private _totalLength: number = 0;

    public updateBezier() {
        if (this._points.length < 2) return;
        let bezier: BezierCurve = null, length, next;
        for (let i = 0, len = this._points.length; i < len; i++) {
            if (i === len - 1 && !this.close) break;
            next = (i + 1) % len;
            bezier = new BezierCurve(this._points[i], this._points[next], this._c2[i], this._c1[next]);
            this._beziers.push(bezier);
            length = bezier.getLength();
            this._totalLength += length;
            this._bezierLengths.push(length);
        }
    }

    getPointAt(length: number) {
        let index = -1;
        for (let i = 0, len = this._bezierLengths.length; i < len; i++) {
            if (this._bezierLengths[i] > length) {
                index = i;
                break;
            }
            else {
                length -= this._bezierLengths[i];
            }
        }

        if (index != -1) {
            return this._beziers[index].getPointAt(length / this._bezierLengths[index]);
        }

        return cc.Vec2.ZERO;
    }

    getLength() {
        return this._totalLength;
    }
}
